﻿using DevelopTool.Bll.DbBlls;
using DevelopTool.Common;
using DevelopTool.Forms.BaseForms;
using DevelopTool.Forms.DbForms.ColumnForms;
using DevelopTool.Forms.DbForms.ExecuteForms;
using DevelopTool.Forms.LodingForm;
using DevelopTool.Model.DbModels.TableRelation;
using ST.Library.UI.NodeEditor;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DevelopTool.Forms.DbForms.TableRelationForms
{
    /// <summary>
    /// 数据库表关系
    /// </summary>
    public partial class TableRelationForm : BaseUIPage
    {
        /// <summary>
        /// 数据库表关系操作类
        /// </summary>
        private TableRelationBll tableRelationBll;

        /// <summary>
        /// 当前关系对象
        /// </summary>
        private TableRelation currentTableRelation;

        /// <summary>
        /// 数据库通用操作类
        /// </summary>
        private DbManagerBll dbManagerBll;

        private TreeNode noteTreeNode;

        /// <summary>
        /// 所有表
        /// </summary>
        private DataTable allTables;

        /// <summary>
        /// 所有实例
        /// </summary>
        private DataTable dataBases;

        /// <summary>
        /// 是否正在删除画布中的节点。 如果为true，那么在删除节点时不提示是否断开连接关系
        /// </summary>
        private bool removestNodeEditorNode = false;

        private Color controlForeColor = Color.White;


        public TableRelationForm(TreeNode noteTreeNode,TableRelation tableRelation)
        {
            InitializeComponent();
            this.currentTableRelation = tableRelation;
            this.noteTreeNode = noteTreeNode;

            this.tableRelationBll = new TableRelationBll();
        }


        private void TableRelationForm_Load(object sender,EventArgs e)
        {
            LoadCanvasNodeData(this.currentTableRelation);

            this.contextMenuStripNode.Renderer = new ToolStripRendererEx();
            this.contextMenuStripNodeEditor.Renderer = new ToolStripRendererEx();
            this.stNodeEditor.NodeAdded += (s,ea) => ea.Node.ContextMenuStrip = this.contextMenuStripNode;
        }


        /// <summary>
        /// 数据库连接选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dbinfoSelectCombo_DbInfoSelected(object sender,CommonControls.DbinfoEventArgs e)
        {
            if(e.DbInfo != null && e.IsConnect)
            {
                this.dbManagerBll = new DbManagerBll(e.DbInfo);

                LoadingHelper.ShowLoading("加载表",() =>
                {
                    this.allTables = this.dbManagerBll.GetTables();
                });

                this.dataBases = GetDataBases(this.allTables);

                #region 初始化数据库实例下拉框数据
                cboDatabase.DataGridView.Init();
                cboDatabase.DataGridView.AddColumn("实例","DatabaseName");
                cboDatabase.DataGridView.AddColumn("表数量","TableCount",30);
                cboDatabase.DataGridView.ReadOnly = true;
                cboDatabase.ValueChanged += CboDatabase_ValueChanged;
                cboDatabase.ShowFilter = true;
                cboDatabase.DataGridView.DataSource = dataBases;
                cboDatabase.DataGridView.MultiSelect = false;//不能多选
                cboDatabase.FilterColumnName = "DatabaseName"; //不设置则全部列过滤
                cboDatabase.Tag = dataBases;
                cboDatabase.DropDownWidth = cboDatabase.Width;

                #endregion

                LoadNavMenuTreeNode(this.dataBases);
            }
            else
            {
                this.dbManagerBll = null;
                cboDatabase.DataGridView.DataSource = null;
                this.uiNavMenuTable.Nodes.Clear();
            }
            SetControlStyle();
        }



        #region 左侧菜单节点拖动事件

        private void uiNavMenuTable_ItemDrag(object sender,ItemDragEventArgs e)
        {

            TreeNode treeNode = e.Item as TreeNode;
            if(treeNode.Name == "TableNode" && e.Button == MouseButtons.Left)
            {
                DoDragDrop(e.Item,stNodeEditor.dragDropEffects);
            }
            else
            {
                DoDragDrop(e.Item,DragDropEffects.None);
            }

        }

        private void uiNavMenuTable_DragEnter(object sender,DragEventArgs e)
        {
            TreeNode treeNode = e.Data.GetData(typeof(TreeNode)) as TreeNode;
            if(treeNode.Name == "TableNode")
            {
                this.uiNavMenuTable.SelectedNode = treeNode;
            }
        }

        #endregion


        #region 左侧菜单搜索

        private void textBoxMenuSearch_ButtonClick(object sender,EventArgs e)
        {
            this.textBoxMenuSearch.Text = string.Empty;
        }

        /// <summary>
        /// 数据库实例筛选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void CboDatabase_ValueChanged(object sender,object value)
        {
            if(value == null)
            {
                cboDatabase.Text = "全部实例";
                LoadNavMenuTreeNode(cboDatabase.Tag as DataTable);
            }
            else
            {
                if(!(cboDatabase.Tag is DataTable dataBases)) return;

                DataGridViewRow dataGridViewRow = value as DataGridViewRow;
                string databaseName = dataGridViewRow.Cells["实例"].Value.ToString();
                cboDatabase.Text = databaseName;

                DataTable table = dataBases.Copy();
                table.Clear();
                foreach(DataRow row in dataBases.Rows)
                {
                    DataRow dataRow = table.NewRow();
                    dataRow["DatabaseName"] = row["DatabaseName"];
                    dataRow["TableCount"] = row["TableCount"];
                    table.Rows.Add(dataRow);
                }
                var dataview = table.DefaultView;
                dataview.RowFilter = $"DatabaseName='{databaseName}'";//筛选条件

                LoadNavMenuTreeNode(dataview.ToTable());
            }
        }

        /// <summary>
        /// 左侧菜单搜索表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxMenuSearch_TextChanged(object sender,EventArgs e)
        {
            if(this.uiNavMenuTable.Nodes.Count <= 0 || this.dbManagerBll == null) return;

            if(string.IsNullOrEmpty(this.textBoxMenuSearch.Text))
            {
                LoadNavMenuTreeNode(cboDatabase.Tag as DataTable);//加载全部
            }
            else
            {
                DataTable tables = this.allTables;

                var dataview = tables.DefaultView;
                dataview.RowFilter = $"TABLE_NAME like '%{this.textBoxMenuSearch.Text}%' or COMMENTS like '%{this.textBoxMenuSearch.Text}%'";
                tables = dataview.ToTable();

                DataTable databaseTables = new DataTable();
                databaseTables.Columns.Add("DatabaseName",typeof(string));
                databaseTables.Columns.Add("TableCount",typeof(int));
                foreach(DataRow row in tables.Rows)
                {
                    if(databaseTables.Select($"DatabaseName='{row["OWNER"]}'").Length <= 0)
                    {
                        DataRow databaseRow = databaseTables.NewRow();
                        databaseRow["DatabaseName"] = row["OWNER"];
                        databaseRow["TableCount"] = 0;
                        databaseTables.Rows.Add(databaseRow);
                    }
                }
                LoadNavMenuTreeNode(databaseTables);

                foreach(TreeNode databaseTreeNode in this.uiNavMenuTable.Nodes[0].Nodes)
                {
                    var dataview2 = tables.DefaultView;
                    dataview2.RowFilter = $"OWNER='{databaseTreeNode.Text}'";
                    LoadNavMenuTableTreeNode(databaseTreeNode,dataview2.ToTable());
                }
            }
        }

        #endregion


        #region 顶部操作按钮事件

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender,EventArgs e)
        {
            SaveCanvas();
        }

        /// <summary>
        /// 另存为
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveAs_Click(object sender,EventArgs e)
        {
            using(SaveFileDialog sfd = new SaveFileDialog())
            {
                sfd.Title = "画布文件另存为";
                sfd.Filter = "*.stn|*.stn";
                sfd.FileName = this.noteTreeNode.Text;
                if(sfd.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
                File.WriteAllBytes(sfd.FileName,this.currentTableRelation.CloneObj().ObjectToByte_Compress());
                this.ShowSuccessNotifier($"已保存到【{sfd.FileName}】");
            }
        }

        /// <summary>
        /// 打开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpen_Click(object sender,EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                Title = "打开画布文件",
                Filter = "*.stn|*.stn"
            };
            if(ofd.ShowDialog() != DialogResult.OK) return;

            bool isContinue;
            if(this.stNodeEditor.Nodes.Count <= 0)
                isContinue = true;//如果画布中没有节点，那就不用提示了。
            else
                isContinue = this.ShowAskDialog($"{GlobalData.AppName_zh}-提示",$"将会覆盖现有的对象关系，是否确定打开？",UIStyle.Orange,true);

            if(isContinue)
            {
                this.stNodeEditor.Nodes.Clear();
                TableRelation tableRelation = File.ReadAllBytes(ofd.FileName).ByteToObject_Decompress<TableRelation>();
                this.LoadCanvasNodeData(tableRelation);
            }
        }

        #endregion


        #region 私有方法

        /// <summary>
        /// 加载左侧【实例】菜单数据
        /// </summary>
        private void LoadNavMenuTreeNode(DataTable dataBases)
        {
            if(dataBases == null || dataBases.Rows.Count <= 0) return;

            this.uiNavMenuTable.Nodes.Clear();

            //创建顶级节点
            TreeNode topTreeNode = this.uiNavMenuTable.CreateNode("表对象集合",Guid.NewGuid());
            this.uiNavMenuTable.SetNodeSymbol(topTreeNode,61641,10);

            //创建实例节点
            foreach(DataRow row in dataBases.Rows)
            {
                string databaseName = row["DatabaseName"].ToString();
                if(string.IsNullOrEmpty(databaseName)) continue;

                //实例节点
                TreeNode databaseTreeNode = topTreeNode.Nodes.Add($"{databaseName}");
                databaseTreeNode.Name = "DatabaseNode";
                // databaseTreeNode.Tag = databaseName;
                this.uiNavMenuTable.SetNodeTipsText(databaseTreeNode,row["TableCount"].ToString(),this.uiNavMenuTable.FillColor,this.controlForeColor);
                this.uiNavMenuTable.SetNodeSymbol(databaseTreeNode,361888,10);

                LoadNavMenuTableTreeNode(databaseTreeNode,GetTables(databaseName,this.allTables));

            }

            //设置顶级节点的Tips文本
            this.uiNavMenuTable.SetNodeTipsText(topTreeNode,topTreeNode.Nodes.Count.ToString(),this.uiNavMenuTable.FillColor,Color.Green);

            topTreeNode.Expand();

        }


        /// <summary>
        /// 加载左侧【表】菜单数据
        /// </summary>
        /// <param name="parentNode"></param>
        private void LoadNavMenuTableTreeNode(TreeNode parentNode,DataTable tablesData = null,bool nodeExpand = false)
        {
            parentNode.Nodes.Clear();

            foreach(DataRow row in tablesData.Rows)
            {
                string TABLE_NAME = row["TABLE_NAME"].ToString();
                string COMMENTS = row["COMMENTS"].ToString();
                string nodeText = string.IsNullOrEmpty(COMMENTS) ? TABLE_NAME : TABLE_NAME + "-" + COMMENTS;

                TreeNode tableTreeNode = new TreeNode(nodeText)
                {
                    Name = "TableNode",
                    Tag = new TableRelationNodeData
                    {
                        Owner = parentNode.Text,
                        TableName = TABLE_NAME,
                        Num_Rows = row["NUM_ROWS"].ToString(),
                        Comments = COMMENTS,
                        Tablespace_Name = row["TABLESPACE_NAME"].ToString(),
                        DbInfo = this.dbManagerBll.dbInfo
                    }
                };
                parentNode.Nodes.Add(tableTreeNode);//添加数据库到数据库信息节点
                this.uiNavMenuTable.SetNodeSymbol(tableTreeNode,361646,10);
            }

            if(nodeExpand)
                parentNode.Expand();//展开节点

            this.EliminateMenuNode();
        }

        /// <summary>
        /// 加载节点数据
        /// </summary>
        /// <param name="tableRelation"></param>
        private void LoadCanvasNodeData(TableRelation tableRelation)
        {
            if(tableRelation.Nodes == null || tableRelation.Nodes.Count <= 0) return;
            //加载表
            foreach(TableRelationNode node in tableRelation.Nodes)
            {
                TableNode tableNode = new TableNode(node)
                {
                    Tag = node.Data,
                };
                this.stNodeEditor.Nodes.Add(tableNode);
                tableNode.ContextMenuStrip = contextMenuStripNode;
            }

            //设置表关系
            List<STNodeOption> inputOptions = new List<STNodeOption>();
            this.stNodeEditor.Nodes.Cast<TableNode>().ForEach(it => { inputOptions.AddRange(it.GetInputOptions()); });

            List<STNodeOption> outputOptions = new List<STNodeOption>();
            this.stNodeEditor.Nodes.Cast<TableNode>().ForEach(it => { outputOptions.AddRange(it.GetOutputOptions()); });

            foreach(TableRelationNodeConnection connection in tableRelation.Connections)
            {
                var inputOption = inputOptions.Find(it => it.Owner.Title == connection.InTableName && it.Text == connection.InColumn);

                var outputOption = outputOptions.Find(it => it.Owner.Title == connection.OutTableName
                && (it.Text == connection.OutColumn || it.Data.ToString() == connection.OutColumnData));

                inputOption.ConnectOption(outputOption);//连接关系
            }

            //设置画布缩放比例
            this.stNodeEditor.ScaleCanvas(tableRelation.CanvasScale,this.stNodeEditor.Width / 2,this.stNodeEditor.Height / 2);
        }

        /// <summary>
        /// 根据画布中的节点剔除左侧菜单中的节点（为实现单一添加）
        /// </summary>
        private void EliminateMenuNode()
        {
            if(this.uiNavMenuTable.Nodes == null || this.uiNavMenuTable.Nodes.Count <= 0) return;
            if(this.stNodeEditor.Nodes == null || this.stNodeEditor.Nodes.Count <= 0) return;

            var databaseTreeNodes = this.uiNavMenuTable.Nodes[0].Nodes.Cast<TreeNode>().ToList();//数据库实例树节点集合


            foreach(TreeNode databaseTreeNode in databaseTreeNodes)
            {
                //更新实例节点中的表数量
                this.uiNavMenuTable.SetNodeTipsText(databaseTreeNode,databaseTreeNode.Nodes.Count.ToString(),this.uiNavMenuTable.FillColor,this.controlForeColor);
            }

            foreach(STNode sTNode in this.stNodeEditor.Nodes)
            {
                if(!(sTNode.Tag is TableRelationNodeData data)) continue;

                var databaseTreeNode = databaseTreeNodes.FirstOrDefault(it => it.Text.ToString() == data.Owner);
                if(databaseTreeNode == null) continue;

                var tableTreeNode = databaseTreeNode.Nodes.Cast<TreeNode>()
                    .FirstOrDefault(it => ((TableRelationNodeData)it.Tag).TableName == data.TableName);
                if(tableTreeNode == null) continue;

                data.TreeNode = tableTreeNode;
                databaseTreeNode.Nodes.Remove(tableTreeNode);
            }
        }

        /// <summary>
        /// 获取实例集合
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private DataTable GetDataBases(DataTable table)
        {
            if(table == null || table.Rows.Count <= 0) return null;

            DataTable databaseTables = new DataTable();
            databaseTables.Columns.Add("DatabaseName",typeof(string));
            databaseTables.Columns.Add("TableCount",typeof(int));
            foreach(DataRow row in table.Rows)
            {
                if(databaseTables.Select($"DatabaseName='{row["OWNER"]}'").Length <= 0)
                {
                    DataRow databaseRow = databaseTables.NewRow();
                    databaseRow["DatabaseName"] = row["OWNER"];
                    databaseRow["TableCount"] = table.Select($"OWNER='{row["OWNER"]}'").Length;
                    databaseTables.Rows.Add(databaseRow);
                }
            }

            return databaseTables;
        }

        /// <summary>
        /// 获取表集合
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="table"></param>
        /// <returns></returns>
        private DataTable GetTables(string databaseName,DataTable table)
        {
            var dataview = table.DefaultView;
            dataview.RowFilter = $"OWNER='{databaseName}'";
            return dataview.ToTable();
        }

        /// <summary>
        /// 保存节点关系
        /// </summary>
        /// <returns></returns>
        private TableRelation SaveCanvas()
        {
            //节点信息
            List<TableRelationNode> nodes = new List<TableRelationNode>();
            foreach(TableNode tableNode in this.stNodeEditor.Nodes)
            {
                TableRelationNode tableRelationNode = new TableRelationNode
                {
                    Title = tableNode.Title,
                    InputOptions = tableNode.GetInputOptions().Select(it => it.Text).ToList(),
                    OutputOptions = tableNode.GetOutputOptions().Select(it => it.Text).ToList(),
                    Rectangle = tableNode.Rectangle,
                    Data = tableNode.Tag as TableRelationNodeData
                };
                nodes.Add(tableRelationNode);
            }


            //连接关系
            List<TableRelationNodeConnection> connections = new List<TableRelationNodeConnection>();
            ConnectionInfo[] connectionInfos = this.stNodeEditor.GetConnectionInfo();
            foreach(ConnectionInfo connectionInfo in connectionInfos)
            {
                TableRelationNodeConnection tableRelationNodeConnection = new TableRelationNodeConnection
                {
                    InTableName = connectionInfo.Input.Owner.Title,
                    InColumn = connectionInfo.Input.Text,
                    InColumnData = connectionInfo.Input.Data.ToString(),

                    OutTableName = connectionInfo.Output.Owner.Title,
                    OutColumn = connectionInfo.Output.Text,
                    OutColumnData = connectionInfo.Output.Data.ToString(),
                };
                connections.Add(tableRelationNodeConnection);
            }

            this.currentTableRelation.Nodes = nodes;
            this.currentTableRelation.Connections = connections;
            this.currentTableRelation.CanvasScale = this.stNodeEditor.CanvasScale;
            this.currentTableRelation = this.tableRelationBll.Save(this.currentTableRelation);

            this.ShowSuccessNotifier("保存成功");

            return this.currentTableRelation;
        }

        /// <summary>
        /// 设置节点属性值
        /// </summary>
        /// <param name="data"></param>
        private void SetNodeProperty(TableRelationNodeData data)
        {
            this.uiSplitContainer2.Panel2Collapsed = false;
            this.stNodePropertyGrid.Text = data.TableName;
            this.txtOWNER.Text = data.Owner;
            this.txtNUM_ROWS.Text = data.Num_Rows;
            this.txtCOMMENTS.Text = data.Comments;
            this.txtTABLESPACE_NAME.Text = data.Tablespace_Name;
        }

        /// <summary>
        /// 清除节点属性
        /// </summary>
        private void ClearNodeProperty()
        {
            this.uiSplitContainer2.Panel2Collapsed = true;
            this.stNodePropertyGrid.Text = string.Empty;
            this.txtOWNER.Text = string.Empty;
            this.txtNUM_ROWS.Text = string.Empty;
            this.txtCOMMENTS.Text = string.Empty;
            this.txtTABLESPACE_NAME.Text = string.Empty;
        }
        #endregion


        #region 画布事件

        /// <summary>
        /// 将表拖放到画布时的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void stNodeEditor_DragDrop(object sender,DragEventArgs e)
        {
            if(!(e.Data.GetData(typeof(TreeNode)) is TreeNode treeNode)) return;

            if(treeNode.Name != "TableNode") return;//只允许放置表

            if(!(treeNode.Tag is TableRelationNodeData data)) return;

            DataTable columnsDataTable = null;
            LoadingHelper.ShowLoading("加载列数据",() =>
            {
                columnsDataTable = this.dbManagerBll.GetTableColumns(data.Owner,data.TableName);
            });

            List<string> inColumns = new List<string>();
            List<string> outColumn = new List<string>();

            //字段名排序
            var dataview = columnsDataTable.DefaultView;
            dataview.Sort = "[COLUMN_ID] ASC";//按表的原始顺序排列
            columnsDataTable = dataview.ToTable();

            foreach(DataRow row in columnsDataTable.Rows)
            {
                inColumns.Add(row["COLUMN_NAME"].ToString());
                outColumn.Add(row["COMMENTS"].ToString());
            }

            Point stNodeEditorPoint = PointToScreen(this.stNodeEditor.Location);//画布控件相对于屏幕的坐标
            //设定节点位置为鼠标放置位置
            Rectangle rectangle = new Rectangle(e.X - stNodeEditorPoint.X - this.uiSplitContainer1.Panel1.Width
                - (this.uiSplitContainer1.SplitterWidth * 5),
                e.Y - stNodeEditorPoint.Y - this.uiTitlePanel3.Height - this.uiTitlePanel3.TitleHeight,0,0);
            TableNode tableNode = new TableNode(data.TableName,inColumns,outColumn,rectangle)
            {
                Tag = data
            };

            this.stNodeEditor.Nodes.Add(tableNode);//将节点添加至画布

            this.EliminateMenuNode();

            this.uiNavMenuTable.SelectedNode = null;//拖动完成后移除菜单选择项
        }

        /// <summary>
        /// 断开连接关系前的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void stNodeEditor_OptionDisConnecting(object sender,STNodeEditorOptionEventArgs e)
        {
            if(removestNodeEditorNode) return;

            this.stNodeEditor.ContextMenuStrip = null;

            STNodeOption opCurrent = e.CurrentOption;
            STNodeOption opTarget = e.TargetOption;

            string msg = $"{opCurrent.Owner.Title}.{opCurrent.Data}={opTarget.Owner.Title}.{opTarget.Data}";
            e.Continue = this.ShowAskDialog($"{GlobalData.AppName_zh}-提示",$"是否确定断开连接关系\n【{msg}】",this.Style,true);
        }


        private void stNodeEditor_MouseDown(object sender,MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Right)//判断点的是不是右键
            {
                if(this.stNodeEditor.ActiveNode == null && this.stNodeEditor.Nodes.Count > 0)
                {
                    this.stNodeEditor.ContextMenuStrip = this.contextMenuStripNodeEditor;
                }
                else
                {
                    this.stNodeEditor.ContextMenuStrip = null;//如果已选中某个节点，则取消画布的右键菜单，不然会重叠
                }
            }
        }


        private void stNodeEditor_ActiveChanged(object sender,EventArgs e)
        {
            if(this.stNodeEditor.ActiveNode == null)
            {
                this.ClearNodeProperty();
                return;
            }

            STNode sTNode = this.stNodeEditor.ActiveNode;
            if(sTNode == null || sTNode.Tag == null || !(sTNode.Tag is TableRelationNodeData data))
            {
                this.ClearNodeProperty();
                return;
            }

            SetNodeProperty(data);

            this.stNodeEditor.ContextMenuStrip = null;//画布中的节点获得焦点后，移除画布的右键菜单
        }
        #endregion


        #region 画布节点右键菜单
        private void 查询表数据ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            if(this.stNodeEditor.ActiveNode.Tag is TableRelationNodeData data)
            {
                UITabControl parentTabControl = this.GetParentControl<UITabControl>();
                if(parentTabControl != null)
                {
                    string sql = $"select * from {data.Owner}.{data.TableName} where 1=1";
                    TabControlHelper.AddPageToTabControl(parentTabControl,new ExecuteSqlForm(data.DbInfo,sql),$"{data.DbInfo.NodeName}-查询",true,$"{data.TableName}-ExecuteSqlForm");
                }
            }
        }

        private void 查看字段详情ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            if(this.stNodeEditor.ActiveNode.Tag is TableRelationNodeData data)
            {
                UITabControl parentTabControl = this.GetParentControl<UITabControl>();
                if(parentTabControl != null)
                {
                    TabControlHelper.AddPageToTabControl(parentTabControl,new OracleTableColumnForm(data.DbInfo,data.Owner,data.TableName),$"{data.DbInfo.NodeName}-字段",true,$"{data.TableName}-OracleTableColumnForm");
                }
            }
        }

        private void 开关锁定节点位置ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            if(this.stNodeEditor.ActiveNode == null) return;

            this.stNodeEditor.ActiveNode.LockLocation = !this.stNodeEditor.ActiveNode.LockLocation;

            string text = this.stNodeEditor.ActiveNode.LockLocation ? "锁定位置固定" : "解除位置固定";
            this.stNodeEditor.ShowAlert($"【{this.stNodeEditor.ActiveNode.Title}】{text}",Color.White,Setting.Theme.BackColor);
        }


        private void 开关禁止连接ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            if(this.stNodeEditor.ActiveNode == null) return;

            this.stNodeEditor.ActiveNode.LockOption = !this.stNodeEditor.ActiveNode.LockOption;

            string text = this.stNodeEditor.ActiveNode.LockOption ? "禁止连接" : "可连接";
            this.stNodeEditor.ShowAlert($"【{this.stNodeEditor.ActiveNode.Title}】{text}",Color.White,Setting.Theme.BackColor);
        }


        /// <summary>
        /// 删除画布中的节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 删除节点ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            if(this.stNodeEditor.ActiveNode == null) return;

            #region 把画布中删除的节点还原到左侧树菜单中
            //还原前提是得先有菜单数据
            if(this.stNodeEditor.ActiveNode.Tag is TableRelationNodeData data && data.TreeNode != null && this.uiNavMenuTable.Nodes.Count > 0)
            {
                if(data.TreeNode is TreeNode tableTreeNode)
                {
                    var databaseTreeNode = this.uiNavMenuTable.Nodes[0].Nodes.Cast<TreeNode>().FirstOrDefault(it => it.Text.ToString() == data.Owner);
                    if(databaseTreeNode != null && !databaseTreeNode.Nodes.Cast<TreeNode>().Any(it => it.Text == tableTreeNode.Text))
                    {
                        databaseTreeNode.Nodes.Insert(0,tableTreeNode);
                    }
                }
            }
            #endregion

            removestNodeEditorNode = true;

            this.stNodeEditor.ShowAlert($"节点【{this.stNodeEditor.ActiveNode.Title}】已删除",Color.White,Setting.Theme.BackColor);
            this.stNodeEditor.Nodes.Remove(this.stNodeEditor.ActiveNode);//从画布中删除节点

            removestNodeEditorNode = false;//删除节点后，设为默认值

            this.EliminateMenuNode();
        }

        #endregion


        #region 画布右键菜单
        private void 清空画布ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            if(!this.ShowAskDialog($"{GlobalData.AppName_zh}-提示",$"是否确定清空画布？",UIStyle.Orange,true)) return;

            removestNodeEditorNode = true;
            this.stNodeEditor.Nodes.Clear();
            removestNodeEditorNode = false;//删除节点后，设为默认值
        }


        private void 将画布保存为图片ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            System.Drawing.Image image = this.stNodeEditor.GetCanvasImage(this.stNodeEditor.ClientRectangle,this.stNodeEditor.CanvasScale);

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Title = "将画布保存为图片",
                Filter = ImageHelper.GetImageFilter(),
                FileName = this.noteTreeNode.Text
            };
            if(saveFileDialog.ShowDialog() != DialogResult.OK) return;

            image.Save(saveFileDialog.FileName,image.RawFormat);

            this.ShowSuccessNotifier($"图片已保存到:【{saveFileDialog.FileName}】");

        }

        /// <summary>
        /// 根据节点连接关系生成查询sql
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 生成查询SqlToolStripMenuItem_Click(object sender,EventArgs e)
        {
            ConnectionInfo[] connectionInfos = this.stNodeEditor.GetConnectionInfo();

            Dictionary<string,string> selectTables = new Dictionary<string,string>();

            int index = 0;
            foreach(ConnectionInfo connectionInfo in connectionInfos)
            {
                STNode outNode = connectionInfo.Output.Owner;
                if(!(outNode.Tag is TableRelationNodeData outData)) continue;
                if(!selectTables.ContainsKey($"{outData.Owner}.{outData.TableName}"))
                {
                    index++;
                    selectTables.Add($"{outData.Owner}.{outData.TableName}",$"t{index}");

                }

                STNode inNode = connectionInfo.Input.Owner;
                if(!(inNode.Tag is TableRelationNodeData inData)) continue;
                if(!selectTables.ContainsKey($"{inData.Owner}.{inData.TableName}"))
                {
                    index++;
                    selectTables.Add($"{inData.Owner}.{inData.TableName}",$"t{index}");
                }
            }

            StringBuilder sqlBuilder = new StringBuilder("select ");//select

            //t1.*,t2.* ...
            foreach(string tname in selectTables.Values)
            {
                sqlBuilder.Append($"{tname}.*,");
            }
            sqlBuilder.Length--;
            sqlBuilder.AppendLine("");

            sqlBuilder.Append("  from ");//from

            //table t1,table t2 ...
            for(int i = 0 ; i < selectTables.Count ; i++)
            {
                var pair = selectTables.ElementAt(i);
                if(i == selectTables.Count - 1)
                    sqlBuilder.AppendLine($"       {pair.Key} {pair.Value}");
                else
                {
                    if(i == 0)
                        sqlBuilder.AppendLine($"{pair.Key} {pair.Value},");
                    else
                        sqlBuilder.AppendLine($"       {pair.Key} {pair.Value},");
                }

            }
            sqlBuilder.AppendLine(" where 1=1");//where 1=1

            //and t1.a=t2.b ...
            foreach(ConnectionInfo connectionInfo in connectionInfos)
            {
                STNode outNode = connectionInfo.Output.Owner;
                STNode inNode = connectionInfo.Input.Owner;

                if(!(outNode.Tag is TableRelationNodeData outData)) continue;
                if(!(inNode.Tag is TableRelationNodeData inData)) continue;

                string outTName = selectTables[$"{outData.Owner}.{outData.TableName}"];
                string inTName = selectTables[$"{inData.Owner}.{inData.TableName}"];

                sqlBuilder.AppendLine($"   and {outTName}.{connectionInfo.Output.Data}={inTName}.{connectionInfo.Input.Data}");
            }

            Clipboard.SetText(sqlBuilder.ToString());
            this.ShowSuccessNotifier("已复制select语句到剪贴板");
        }

        #endregion

        private void TableRelationForm_VisibleChanged(object sender,EventArgs e)
        {
            SetControlStyle();
        }


        /// <summary>
        /// 设置控件主题
        /// </summary>
        private void SetControlStyle()
        {
            UIMenuStyle uIMenuStyle = Setting.Theme.ControlThemColor;

            switch(uIMenuStyle)
            {
                case UIMenuStyle.Black:

                    this.controlForeColor = Color.White;

                    this.stNodeEditor.BackColor = Color.FromArgb(34,34,34);

                    this.stNodePropertyGrid.FillColor = ThemHelper.CustomBackColor_Black;
                    this.stNodePropertyGrid.ForeColor = Color.White;
                    this.stNodePropertyGrid.TitleColor = ThemHelper.CustomBackColor_Black;
                    this.stNodePropertyGrid.TitleForeColor = Color.White;

                    break;
                case UIMenuStyle.White:

                    this.controlForeColor = Color.Black;

                    this.stNodeEditor.BackColor = Color.WhiteSmoke;

                    this.stNodePropertyGrid.FillColor = ThemHelper.CustomBackColor_White;
                    this.stNodePropertyGrid.ForeColor = Color.Black;
                    this.stNodePropertyGrid.TitleColor = ThemHelper.CustomBackColor_White;
                    this.stNodePropertyGrid.TitleForeColor = Color.Black;

                    break;
            }
        }

        /// <summary>
        /// 左侧【实例】菜单控件大小改变时重新渲染下数据，不然滚动条显示不正确。这个bug以后可能会彻底解决的吧~
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uiNavMenuTable_SizeChanged(object sender,EventArgs e)
        {
            // LoadNavMenuTreeNode(this.dataBases);
        }
    }
}
